package com.miyake.dsp.common;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang.ArrayUtils;

import com.miyake.dsp.osa.lab.EdgeNotFoundException;
import com.miyake.dsp.osa.lab.NoiseDetector;
import com.miyake.dsp.osa.lab.Sort;

public class DataMerger {



	class PeakProp {
		public PeakProp(int start, int end) {
			this.start = start;
			this.end = end;
		}
		int start;
		int end;
	};
	Map<Integer, PeakProp> peakMap = new HashMap<Integer, PeakProp>();
	
	public DataMerger(double[] y) {
		double[] x = new double[y.length];
		
		for (int i = 0; i < x.length; i++) {
			x[i] = i;
		}
		NoiseDetector nd = new NoiseDetector();
		try {
			nd.setData(x, y);
		} catch (EdgeNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		double threshold = nd.getNoiseFloor();
				
		Sort sort = new Sort(x, y);
		double[] sortedX = sort.getOutx();
		double[] sortedY = sort.getOuty();
		
		double[] subx = null;
		double[] suby;
		for (int i = 0; i < sortedY.length; i++) {
			if (sortedY[i] > threshold) {
				subx = ArrayUtils.subarray(sortedX, i, sortedX.length-1);
				suby = ArrayUtils.subarray(sortedY, i, sortedY.length-1);
				break;
			}
		}
		if (subx == null) {
			return;
		}
		
		Sort sort2 = new Sort(subx);
		int[] indexes = sort2.getOutXindex();
		
		final Set<Integer> startSet = new TreeSet<Integer>();
		final Set<Integer> endSet = new TreeSet<Integer>();
		
		for (int i = 0; i < indexes.length; i++) {
			new SearchSeparation(indexes[i], y) {
				@Override
				public void result(int start, int end, int max) {
					peakMap.put(max, new PeakProp(start, end));
				}
			};
		}
		
	}
	
	abstract class SearchSeparation {
		abstract public void result(int start, int end, int max);
		public SearchSeparation(int index, double[] y) {
			int start = 0;
			int end = 0;
			int max = 0;
			double maxVal = Double.MIN_VALUE;
			
			// To right
			for (int i = index; i < y.length - 1; i++) {
				if (y[i] > maxVal) {
					maxVal = y[i];
					max = i;
				}
				double diff = y[i+1] - y[i];
				if (diff > 0) {
					end = i;
					break;
				}
			}
			
			// To left
			for (int i = index; i > 0; i--) {
				if (y[i] > maxVal) {
					maxVal = y[i];
					max = i;
				}
				double diff = y[i-1] - y[i];
				if (diff < 0) {
					start = i;
					break;
				}
			}
			result(start, end, max);
		}
	}
	
	public int[] getPeaks() {
		Set<Integer> set = new TreeSet(peakMap.keySet());
		return ArrayUtils.toPrimitive(set.toArray(new Integer[0]));
	}
}
